package com.jhws.core.shiro.CredentialsMatcher;

import com.jhws.common.base.bo.Global;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.factory.annotation.Autowired;

import com.jhws.sys.user.service.ITblUserDimService;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 用于检测web登录页面账号密码是否匹配
 */
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    @Autowired
    ITblUserDimService IUserService;

    @Resource
    protected RedisTemplate stringTemplate;

    /**
     * shiro login方法中被自动回调来判断账号密码是否匹配的接口
     * @param token 包含了账号和密码
     * @param info
     * @return
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = ((UsernamePasswordToken) token).getUsername();
        char[] pwd = ((UsernamePasswordToken) token).getPassword();
        String Password = new String(pwd);
        //retry count + 1

        ValueOperations valueOperations = stringTemplate.opsForValue();
        String retryCount = "";
        try {
            retryCount = (String) valueOperations.get(Global.REDIS_LOGIN_LOCK_PREFIX + username);
            if (retryCount == null) {
                retryCount = "0";
            }
        }catch(Exception e){
            e.printStackTrace();
            throw new RedisConnectionFailureException("");
        }

        if (Integer.valueOf(retryCount) == -1) {
            throw new AccountException();
        } else if ((Integer.valueOf(retryCount) + 1) > Global.LOGIN_PASSWORD_FAIL_COUNT) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException();
        } else {
            valueOperations.set(Global.REDIS_LOGIN_LOCK_PREFIX + username, (String.valueOf(Integer.valueOf(retryCount) + 1)));
            stringTemplate.expire(Global.REDIS_LOGIN_LOCK_PREFIX + username, 60, TimeUnit.MINUTES);
        }

        boolean matches = IUserService.login(username, Password);
        if (matches) {
            //clear retry count
            stringTemplate.delete(Global.REDIS_LOGIN_LOCK_PREFIX + username);
        }
        return matches;
    }
}
